//--------------------------------------------------------------------------------------
// File: MeshFromOBJ10.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------

float3 g_vMaterialAmbient   = float3( 0.2f, 0.2f, 0.2f );   // Material's ambient color
float  g_fMaterialAlpha     = 1.0f;

Texture2D g_MeshTexture;        // Color texture for mesh
Texture2DMS<float4, MSAA_SAMPLES_COUNT>	g_MSAATexture;
matrix g_mWorldViewProjection ; // World * View * Projection matrix

//--------------------------------------------------------------------------------------
// Texture sampler
//--------------------------------------------------------------------------------------
SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

//States
BlendState SrcAlphaBlend
{
   BlendEnable[0]           = TRUE;
   SrcBlend                 = SRC_ALPHA;
   DestBlend                = INV_SRC_ALPHA;
   BlendOp                  = ADD;
   SrcBlendAlpha            = SRC_ALPHA;
   DestBlendAlpha           = INV_SRC_ALPHA;
   BlendOpAlpha             = ADD;
   AlphaToCoverageEnable	= TRUE;
   RenderTargetWriteMask[0] = 0x0F;
};

RasterizerState DisableCulling 
{ 
	CullMode = None; 
};

struct VSMESH_INPUT
{
    float3 vPosObject   : POSITION;
    float3 vNormalObject: NORMAL;
    float2 vTexUV       : TEXCOORD0;
};

struct PSMESH_INPUT
{
   float4 vPos		: SV_POSITION;
   float2 vTexUH	: TEXCOORD0;
   float3 vNorm		: TEXCOORD1;
   float4 vColor	: COLOR0;
};

PSMESH_INPUT VSMesh( VSMESH_INPUT input)
{
    PSMESH_INPUT output;
    
    output.vPos = mul( float4(input.vPosObject,1), g_mWorldViewProjection );
    output.vTexUH = input.vTexUV;
	output.vNorm = input.vNormalObject.xyz;

    output.vColor.rgb = g_vMaterialAmbient;
    output.vColor.a = g_fMaterialAlpha;

    return output;
}

float4 PSMesh( PSMESH_INPUT input ) : SV_Target
{
    float4 output = input.vColor;

    output *= g_MeshTexture.Sample( samLinear, input.vTexUH );
    if (output.a < 0.5f)
		discard;

    return output;
}

struct VSTEXTURE_INPUT
{
    float3 vPos: POSITION;
    float2 vTexUV: TEXCOORD0;
};

struct PSTEXTURE_INPUT
{
   float4 vPos     : SV_POSITION;
   float2 vTexUV   : TEXCOORD;
};

PSTEXTURE_INPUT VSTextureQuad( VSTEXTURE_INPUT input)
{
    PSTEXTURE_INPUT output;
        
    output.vPos = float4(input.vPos, 1);
    output.vTexUV = input.vTexUV;

    return output;
}

float4 PSTextureQuad( PSTEXTURE_INPUT input ) : SV_Target
{
	float4 result = {0,0,0,0};
	float4 sampleColor = {0,0,0,0};
	int width, height, samples;
	g_MSAATexture.GetDimensions(width, height, samples);
	for( int i = 0; i < samples; i++ ) 
	{ 
		  sampleColor = g_MSAATexture.Load(int2(int2(width, height)*input.vTexUV),  i);
		  if (sampleColor.a > result.a)
			result = sampleColor;
	}

	return result;
}

float4 PSMeshNormals( PSMESH_INPUT input ) : SV_Target
{
	return float4((input.vNorm.xyz + float3(1.f, 1.f, 1.f))*0.5f, 1.f);
}

float4 PSTextureNormQuad( PSTEXTURE_INPUT input ) : SV_Target
{
	float4 result = {0,0,0,1};
	float4 sampleColor = {0,0,0,0};
	int width, height, samples, count;
	g_MSAATexture.GetDimensions(width, height, samples);
	
	count = 0;
	for( int i = 0; i < samples; i++ )
	{
		  sampleColor = g_MSAATexture.Load(int2(int2(width, height)*input.vTexUV),  i);
		  if (sampleColor.a > 0.03125f)
		  {
			  result += sampleColor;
			  ++count;
		  }
	}

	if (count > 0)
		result /= count;

	return result;
}

//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------
technique10 TexturedMesh
{
    pass P0
    {
		SetRasterizerState(DisableCulling);
		SetBlendState(SrcAlphaBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
        SetVertexShader( CompileShader( vs_5_0, VSMesh() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_5_0, PSMesh() ) );
    }
}

technique10 RenderTextureQuad
{
    pass P0
    {
		SetVertexShader( CompileShader( vs_5_0, VSTextureQuad() ) );
        SetPixelShader( CompileShader( ps_5_0, PSTextureQuad() ) );
    }
}

technique10 RenderMeshNormals
{
    pass P0
    {
		SetRasterizerState(DisableCulling);
		SetBlendState(SrcAlphaBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
        SetVertexShader( CompileShader( vs_5_0, VSMesh() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_5_0, PSMeshNormals() ) );
    }
}
technique10 RenderNormTextureQuad
{
    pass P0
    {
		SetVertexShader( CompileShader( vs_5_0, VSTextureQuad() ) );
        SetPixelShader( CompileShader( ps_5_0, PSTextureNormQuad() ) );
    }
}